import tkinter as tk
from tkinter import ttk
from openai import OpenAI
import threading
import time
import os
from encryption_utils import EncryptionUtils

class AIAssistant:
    def __init__(self, parent, terminal_app):
        self.parent = parent
        self.terminal_app = terminal_app
        self.is_visible = False
        self.current_tab_index = -1
        self.chat_history = {}
        self.alt_press_count = 0
        self.last_alt_press = 0
        self.drag_data = {'x': 0, 'y': 0}  # 初始化拖动数据
        self.frame_x = 0  # 存储窗口x坐标
        self.frame_y = 0  # 存储窗口y坐标
        
        # 初始化加密工具并获取API密钥
        self.encryption_utils = EncryptionUtils()
        api_key = self.get_api_key()
        
        # 保存当前使用的密钥名称
        self.current_key_name = self._load_selected_key_name()
        
        # 初始化DeepSeek客户端
        self.client = OpenAI(
            api_key=api_key,
            base_url="https://api.deepseek.com"
        )
        
        # 创建聊天窗口
        self.create_ui()
        
        # 绑定Alt键双击事件 - 尝试不同的绑定方式以确保捕获
        self.parent.bind('<Alt_L>', self.on_alt_press)
        self.parent.bind('<KeyPress-Alt_L>', self.on_alt_press)
        
        # 绑定标签页切换事件（从主应用获取）
        self.terminal_app.tab_control.bind("<<NotebookTabChanged>>", self.on_tab_changed)
    
    def get_api_key(self):
        """从密钥管理器获取API密钥"""
        try:
            keys = self.encryption_utils.load_keys()
            # 如果没有密钥，返回空字符串
            if not keys:
                return ""
            
            # 尝试加载选定的密钥
            selected_key_name = self._load_selected_key_name()
            if selected_key_name and selected_key_name in keys:
                return keys[selected_key_name]
            
            # 如果没有找到选定的密钥，但有默认密钥名称，尝试使用它
            if hasattr(self, 'current_key_name') and self.current_key_name and self.current_key_name in keys:
                return keys[self.current_key_name]
            
            # 查找DeepSeek相关的密钥
            for name, key in keys.items():
                if "deepseek" in name.lower():
                    return key
            
            # 如果没有找到特定名称的密钥，返回第一个密钥
            return list(keys.values())[0]
        except Exception as e:
            print(f"获取API密钥时出错: {e}")
            return ""
    
    def _load_selected_key_name(self):
        """加载选定的密钥名称"""
        try:
            if os.path.exists("selected_key.json"):
                with open("selected_key.json", "r", encoding="utf-8") as f:
                    data = json.load(f)
                    return data.get("selected_key", "")
            return ""
        except Exception:
            return ""
    
    def create_ui(self):
        # 创建聊天窗口框架
        self.frame = ttk.Frame(self.parent, width=400, height=150, relief=tk.RAISED, borderwidth=1)
        # 初始位置设置在右下角
        self.frame.place(relx=1.0, rely=1.0, anchor=tk.SE, x=-20, y=-20)  # 距离右下角20像素
        # 保存初始位置
        self.frame_x = self.frame.winfo_x()
        self.frame_y = self.frame.winfo_y()
        self.frame.lower()  # 默认隐藏
        
        # 添加窗口拖动功能
        self.frame.bind('<Button-1>', self.on_drag_start)
        self.frame.bind('<B1-Motion>', self.on_drag_motion)
        
        # 展示框
        display_frame = ttk.Frame(self.frame)
        display_frame.pack(fill=tk.X, padx=10, pady=(10, 5))
        
        self.display_text = tk.Text(display_frame, height=1, width=40, state=tk.DISABLED)
        self.display_text.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        # 插入按钮
        self.insert_button = ttk.Button(display_frame, text="→", width=3, command=self.insert_command)
        self.insert_button.pack(side=tk.RIGHT)
        
        # 输入框和按钮
        input_frame = ttk.Frame(self.frame)
        input_frame.pack(fill=tk.X, padx=10, pady=5)
        
        self.input_text = ttk.Entry(input_frame, width=40)
        self.input_text.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 5))
        # 确保回车键用于发送消息而不是换行
        self.input_text.bind('<Return>', lambda event: self.send_message())
        
        self.send_button = ttk.Button(input_frame, text="发送", width=6, command=self.send_message)
        self.send_button.pack(side=tk.LEFT, padx=(0, 5))
        
        self.clear_button = ttk.Button(input_frame, text="清除", width=6, command=self.clear_chat)
        self.clear_button.pack(side=tk.LEFT)
    
    def toggle_visibility(self):
        if self.is_visible:
            self.frame.lower()
        else:
            # 获取当前标签页索引
            current_tab_idx = self.terminal_app.tab_control.index(self.terminal_app.tab_control.select())
            self.current_tab_index = current_tab_idx
            
            # 如果当前标签页没有聊天历史，初始化
            if current_tab_idx not in self.chat_history:
                self.chat_history[current_tab_idx] = [
                    {"role": "system", "content": "你是一个命令行助手，只输出命令，不要任何解释、说明或额外内容。"}
                ]
            
            # 确保窗口在之前保存的位置显示
            if self.frame_x != 0 or self.frame_y != 0:
                self.frame.place_configure(x=self.frame_x, y=self.frame_y, anchor='nw')
            
            self.frame.lift()
            
            # 自动聚焦到输入框，无需手动点击
            self.input_text.focus_set()
        self.is_visible = not self.is_visible
    
    def on_alt_press(self, event):
        # 添加调试信息
        print(f"Alt键被按下，当前计数: {self.alt_press_count}")
        
        current_time = time.time()
        
        # 修复时间初始化问题
        if self.last_alt_press == 0:
            # 第一次按键，初始化last_alt_press
            self.last_alt_press = current_time
            self.alt_press_count = 1
            print("第一次按键，初始化计数")
            return 'continue'
        
        # 计算时间差
        time_diff = current_time - self.last_alt_press
        print(f"两次按键间隔: {time_diff:.3f}秒")
        
        # 检测双击（500毫秒内）
        if time_diff < 0.5:
            self.alt_press_count += 1
            print(f"短时间内再次按键，计数增加到: {self.alt_press_count}")
        else:
            self.alt_press_count = 1
            print(f"按键间隔过长，重置计数为: {self.alt_press_count}")
        
        self.last_alt_press = current_time
        
        # 确保事件不会被系统其他部分处理
        event.widget.focus_set()
        
        # 只要检测到两次或更多按键就触发（为了更灵敏）
        if self.alt_press_count >= 2:
            print("检测到Alt键双击，切换AI助手可见性")
            self.toggle_visibility()
            self.alt_press_count = 0
        
        # 阻止事件冒泡，确保我们的处理优先
        return 'break'
    
    def on_drag_start(self, event):
        # 记录开始拖动时的鼠标位置和窗口位置
        self.drag_data['x'] = event.x
        self.drag_data['y'] = event.y
        self.frame_x = self.frame.winfo_x()
        self.frame_y = self.frame.winfo_y()
        
    def on_drag_motion(self, event):
        # 计算鼠标移动的距离
        delta_x = event.x - self.drag_data['x']
        delta_y = event.y - self.drag_data['y']
        
        # 计算新的窗口位置
        x = self.frame_x + delta_x
        y = self.frame_y + delta_y
        
        # 移动窗口 - 使用相对定位
        self.frame.place_configure(x=x, y=y, anchor='nw')
        
        # 保存新位置
        self.frame_x = x
        self.frame_y = y
        
    def on_tab_changed(self, event):
        # 切换标签页时隐藏AI助手
        if self.is_visible:
            self.frame.lower()
            self.is_visible = False
        
        # 更新当前标签页索引
        current_tab_idx = self.terminal_app.tab_control.index(self.terminal_app.tab_control.select())
        self.current_tab_index = current_tab_idx
        
        # 如果当前标签页没有聊天历史，初始化
        if current_tab_idx not in self.chat_history:
            self.chat_history[current_tab_idx] = [
                {"role": "system", "content": "你是一个命令行助手，只输出命令，不要任何解释、说明或额外内容。"}
            ]
    
    def send_message(self, event=None):
        user_message = self.input_text.get().strip()
        if not user_message or self.current_tab_index == -1:
            return
        
        # 更新聊天历史
        self.chat_history[self.current_tab_index].append({"role": "user", "content": user_message})
        
        # 清空输入框
        self.input_text.delete(0, tk.END)
        
        # 在单独线程中调用API，避免界面卡顿
        threading.Thread(target=self._call_api).start()
        
        # 阻止回车键的默认换行行为
        return 'break'
    
    def update_api_key(self):
        """更新API密钥"""
        # 获取新的API密钥
        new_key_name = self._load_selected_key_name()
        new_api_key = self.get_api_key()
        
        # 检查密钥是否发生变化
        if new_key_name != self.current_key_name or new_api_key != self.client.api_key:
            # 更新当前密钥名称
            self.current_key_name = new_key_name
            
            # 更新客户端的API密钥
            self.client = OpenAI(
                api_key=new_api_key,
                base_url="https://api.deepseek.com"
            )
            
            print(f"AI助手API密钥已更新，当前使用密钥: {new_key_name if new_key_name else '默认密钥'}")

    def _call_api(self):
        try:
            # 更新API密钥以确保使用最新的密钥
            self.update_api_key()
            
            # 获取当前终端标签页的命令历史
            current_terminal_history = self._get_current_terminal_history()
            
            # 获取当前终端的完整输出内容
            terminal_output = ""
            if 0 <= self.current_tab_index < len(self.terminal_app.terminal_tabs):
                current_terminal = self.terminal_app.terminal_tabs[self.current_tab_index]
                terminal_output = current_terminal.terminal_text.get(1.0, tk.END)[-2000:]  # 只取最后2000个字符
            
            # 创建包含终端历史的消息列表
            messages_with_history = self.chat_history[self.current_tab_index].copy()
            
            # 如果有终端历史，添加到系统消息中
            if current_terminal_history:
                # 获取原始系统消息
                original_system_message = messages_with_history[0]["content"]
                # 添加终端历史信息
                system_message_with_history = f"{original_system_message}\n\n用户最近在终端中执行的命令: {'; '.join(current_terminal_history)}"
                
                # 添加终端的完整输出内容
                if terminal_output:
                    system_message_with_history += f"\n\n终端最近的输出内容:\n{terminal_output}"
                
                messages_with_history[0]["content"] = system_message_with_history
            
            # 调用DeepSeek API，结合终端历史
            response = self.client.chat.completions.create(
                model="deepseek-chat",
                messages=messages_with_history,
                stream=False
            )
            
            # 获取AI回复
            ai_message = response.choices[0].message.content.strip()
            
            # 更新聊天历史
            self.chat_history[self.current_tab_index].append({"role": "assistant", "content": ai_message})
            
            # 更新展示框
            self.display_text.config(state=tk.NORMAL)
            self.display_text.delete(1.0, tk.END)
            self.display_text.insert(tk.END, ai_message)
            self.display_text.config(state=tk.DISABLED)
        except Exception as e:
            # 显示错误信息
            self.display_text.config(state=tk.NORMAL)
            self.display_text.delete(1.0, tk.END)
            self.display_text.insert(tk.END, f"API调用失败: {str(e)}")
            self.display_text.config(state=tk.DISABLED)
    
    def insert_command(self):
        if not self.is_visible or self.current_tab_index == -1:
            return
        
        # 获取展示框中的命令
        command = self.display_text.get(1.0, tk.END).strip()
        if not command:
            return
        
        # 插入到当前终端标签页
        if 0 <= self.current_tab_index < len(self.terminal_app.terminal_tabs):
            current_terminal = self.terminal_app.terminal_tabs[self.current_tab_index]
            current_terminal.insert_text(command)
    
    def clear_chat(self):
        if self.current_tab_index == -1:
            return
        
        # 重置聊天历史，只保留系统消息
        self.chat_history[self.current_tab_index] = [
            {"role": "system", "content": "你是一个命令行助手，只输出命令，不要任何解释、说明或额外内容。"}
        ]
        
        # 清空展示框
        self.display_text.config(state=tk.NORMAL)
        self.display_text.delete(1.0, tk.END)
        self.display_text.config(state=tk.DISABLED)
    
    def _get_current_terminal_history(self):
        """获取当前终端标签页的命令历史，返回最近5条命令"""
        if self.current_tab_index == -1:
            return []
        
        try:
            if 0 <= self.current_tab_index < len(self.terminal_app.terminal_tabs):
                current_terminal = self.terminal_app.terminal_tabs[self.current_tab_index]
                # 返回最近5条命令，避免历史过长影响API调用
                return current_terminal.command_history[-5:] if current_terminal.command_history else []
            return []
        except Exception:
            return []